﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using l1cs.server.model.Instance;
using l1cs.server.serverpackets;
using l1cs.server.datatables;
using l1cs.server.model;
using l1cs.server.model.skill;

namespace l1cs.server.clientpackets
{
    public class C_UseSkill : ClientBasePacket
    {
        private static Logger _log = Logger.getLogger( typeof( C_UseSkill ).FullName );

        public C_UseSkill( byte[] abyte0, ClientThread client )
            : base( abyte0 )
        {
            int row = readC();
            int column = readC();
            int skillId = ( row * 8 ) + column + 1;
            String charName = null;
            String message = null;
            int targetId = 0;
            int targetX = 0;
            int targetY = 0;
            L1PcInstance pc = client.getActiveChar();

            if ( pc.isTeleport() || pc.isDead() )
            {
                return;
            }
            if ( !pc.getMap().isUsableSkill() )
            {
                pc.sendPackets( new S_ServerMessage( 563 ) ); // \f1ここでは使えません。
                return;
            }
            if ( !pc.isSkillMastery( skillId ) )
            {
                return;
            }

            // 要求間隔をチェックする
            if ( Config.CHECK_SPELL_INTERVAL )
            {
                int result;
                // FIXME どのスキルがdir/no dirであるかの判断が適当
                if ( SkillsTable.getInstance().getTemplate( skillId ).getActionId() ==
                            ActionCodes.ACTION_SkillAttack )
                {
                    result = pc.getAcceleratorChecker().checkInterval(
                            AcceleratorChecker.ACT_TYPE.SPELL_DIR );
                }
                else
                {
                    result = pc.getAcceleratorChecker().checkInterval(
                            AcceleratorChecker.ACT_TYPE.SPELL_NODIR );
                }
                if ( result == AcceleratorChecker.R_DISCONNECTED )
                {
                    return;
                }
            }

            if ( abyte0.Length > 4 )
            {
                if ( skillId == L1SkillId.CALL_CLAN || skillId == L1SkillId.RUN_CLAN )
                { // コールクラン、ランクラン
                    charName = readS();
                }
                else if ( skillId == L1SkillId.TRUE_TARGET )
                { // トゥルーターゲット
                    targetId = readD();
                    targetX = readH();
                    targetY = readH();
                    message = readS();
                }
                else if ( skillId == L1SkillId.TELEPORT || skillId == L1SkillId.MASS_TELEPORT )
                { // テレポート、マステレポート
                    readH(); // MapID
                    targetId = readD(); // Bookmark ID
                }
                else if ( skillId == L1SkillId.FIRE_WALL || skillId == L1SkillId.LIFE_STREAM )
                { // ファイアーウォール、ライフストリーム
                    targetX = readH();
                    targetY = readH();
                }
                else
                {
                    targetId = readD();
                    targetX = readH();
                    targetY = readH();
                }
            }

            if ( pc.hasSkillEffect( L1SkillId.ABSOLUTE_BARRIER ) )
            { // アブソルート バリアの解除
                pc.killSkillEffectTimer( L1SkillId.ABSOLUTE_BARRIER );
                pc.startHpRegeneration();
                pc.startMpRegeneration();
                pc.startMpRegenerationByDoll();
            }
            pc.killSkillEffectTimer( L1SkillId.MEDITATION );

            if ( skillId == L1SkillId.CALL_CLAN || skillId == L1SkillId.RUN_CLAN )
            { // コールクラン、ランクラン
                if ( charName.Length == 0 )
                {
                    // 名前が空の場合クライアントで弾かれるはず
                    return;
                }

                L1PcInstance target = L1World.getInstance().getPlayer( charName );

                if ( target == null )
                {
                    // メッセージが正確であるか未調査
                    pc.sendPackets( new S_ServerMessage( 73, charName ) ); // \f1%0はゲームをしていません。
                    return;
                }
                if ( pc.getClanid() != target.getClanid() )
                {
                    pc.sendPackets( new S_ServerMessage( 414 ) ); // 同じ血盟員ではありません。
                    return;
                }
                targetId = target.getId();
                if ( skillId == L1SkillId.CALL_CLAN )
                {
                    // 移動せずに連続して同じクラン員にコールクランした場合、向きは前回の向きになる
                    int callClanId = pc.getCallClanId();
                    if ( callClanId == 0 || callClanId != targetId )
                    {
                        pc.setCallClanId( targetId );
                        pc.setCallClanHeading( pc.getHeading() );
                    }
                }
            }
            L1SkillUse l1skilluse = new L1SkillUse();
            l1skilluse.handleCommands( pc, skillId, targetId, targetX, targetY,
                    message, 0, L1SkillUse.TYPE_NORMAL );
        }
    }
}